﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Audit.SqlServer.Providers;
using Dapper_Core.AutoJob;
using Dapper_Core.DAL.Impl;
using Dapper_Core.Model;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization;
using NLog;
using NLog.Extensions.Logging;
using NLog.Web;
using Quartz;
using Quartz.Impl;
using UEditor.Core;

namespace Dapper_Core.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;

            //读取appsettings.json中的配置项
            Appsettings.Initial(configuration);

            //处理SqlMap.xml
            ReadSQLXml.Init();

            //配置NLog（1）
            env.ConfigureNLog("nlog.config");
            LogManager.Configuration.Variables["connectionString"] = Configuration["SqlServerConnection01:Value"];
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            //[Controller中使用Session（1）]添加Session
            services.AddDistributedMemoryCache();

            //非Controller使用Session（1）
            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            //设置Session过期时间
            services.AddSession(o => { o.IdleTimeout = TimeSpan.FromMinutes(30); });

            //设置Core可以存储Cookie
            services.Configure<CookiePolicyOptions>(option => { option.CheckConsentNeeded = context => false; });

            //Core中使用UEditor
            services.AddUEditorService();

            //添加全局过滤器
            services.AddMvc(options => { options.Filters.Add(new CheckSessionFilter() { IsCheck = true }); });

            //启用Quartz(1)
            services.AddQuartz(typeof(QuartzJob));

            //注释掉以下6行内容后可以跨Controller读写Session
            //services.Configure<CookiePolicyOptions>(options =>
            //{
            //    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            //    options.CheckConsentNeeded = context => true;
            //    options.MinimumSameSitePolicy = SameSiteMode.None;
            //});

            //属性注入[第二步]
            services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

            //对 JSON 数据使用混合大小写。跟属性名同样的大小写输出
            services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.ContractResolver = new DefaultContractResolver(); });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            //注册Autofac组件
            return AutofacComponent.Register(services);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            //配置NLog（2）
            loggerFactory.AddNLog();
            app.AddNLogWeb();

            //配置Audit日志记录方式
            Audit.Core.Configuration.DataProvider = new SqlDataProvider()
            {
                ConnectionString = Appsettings.SqlServerConnection01.Value,
                Schema = "dbo",
                TableName = "Sys_AuditLog",
                IdColumnName = "Id",
                CustomColumns = new List<Audit.SqlServer.CustomColumn>()
                {
                    new Audit.SqlServer.CustomColumn("Module", auditEvent => auditEvent.CustomFields["Module"] ?? ""),
                    new Audit.SqlServer.CustomColumn("Operator", auditEvent => auditEvent.CustomFields["Operator"] ?? ""),
                    new Audit.SqlServer.CustomColumn("Operation", auditEvent => auditEvent.CustomFields["Operation"] ?? "")
                },
                JsonColumnName = "Data",
                LastUpdatedDateColumnName = "CreateDate"
            };

            //启用Quartz(2)
            QuartzArtifiService.StartJobs<QuartzJob>();

            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Upload")),
                RequestPath = "/Upload",
                OnPrepareResponse = ctx =>
                {
                    ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=36000");
                }
            });

            //[Controller中使用Session（2）]启用Session
            app.UseSession();

            //非Controller使用Session（2）
            app.UseStaticHttpContext();

            app.UseMvc(routes =>
            {
                routes.MapAreaRoute(
                    name: "areaSys",
                    areaName: "Sys",
                    template: "Sys/{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });

                routes.MapAreaRoute(
                    name: "areaPersonalAccount",
                    areaName: "PersonalAccount",
                    template: "PersonalAccount/{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });

                routes.MapAreaRoute(
                    name: "areaWorkflow",
                    areaName: "Workflow",
                    template: "Workflow/{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });

                routes.MapAreaRoute(
                    name: "areaAgent",
                    areaName: "Agent",
                    template: "Agent/{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });

                routes.MapAreaRoute(
                    name: "areaManufacturer",
                    areaName: "Manufacturer",
                    template: "Manufacturer/{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Login}/{action=Index}/{id?}");
            });
        }
    }
}
